package org.example.learningplanassistant.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.BCrypt;
import lombok.extern.slf4j.Slf4j;
import org.example.learningplanassistant.dto.LoginFormDTO;
import org.example.learningplanassistant.dto.RegisterFormDTO;
import org.example.learningplanassistant.dto.Result;
import org.example.learningplanassistant.dto.UserDTO;
import org.example.learningplanassistant.pojo.User;
import org.example.learningplanassistant.dao.UserMapper;
import org.example.learningplanassistant.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.learningplanassistant.utils.EmailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.example.learningplanassistant.utils.RegexUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static org.example.learningplanassistant.utils.RedisConstants.*;
import static org.example.learningplanassistant.utils.SystemConstants.USER_NAME_PREFIX;

/**
 * <p>
 * 用户信息表 服务实现类
 * </p>
 *
 * @author gcbsh
 * @since 2025-03-24
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private EmailService emailService;

    /**
     * 发送验证码功能
     * @param phone 手机号码
     */
    @Override
    public Result sendCode(String phone) {
        if(RegexUtils.isPhoneInvalid(phone)){
            return Result.fail("手机号格式错误！");
        }
        String code = RandomUtil.randomNumbers(6);

        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,1, TimeUnit.MINUTES);

//        5.发送验证码(调用阿里云短信验证码)
//        --------------------
        emailService.sendSimpleMail("664656164@qq.com","欢迎登录学习规划助理app|邮箱验证码",code);
        log.debug("发送短信验证码成功，验证码：{}"+code);
        return Result.ok();
    }
    /**
     * 注册功能
     * @param registerForm 注册参数，包含手用户名、密码
     */
    @Override
    public Result register(RegisterFormDTO registerForm) {
        String username = registerForm.getName();
        String password = registerForm.getPassword();

        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
            return Result.fail("用户名或密码不能为空");
        }
        User user = null;
        user = query().eq("name", username).one();
        if(user != null){
            return Result.fail("用户已存在");
        }
        user = new User();
        user.setName(username);
//        byte[] bytes = password.getBytes(StandardCharsets.UTF_8);
//        password = DigestUtils.md5DigestAsHex(bytes);
        user.setPassword(BCrypt.hashpw(password, BCrypt.gensalt()));
        boolean save = save(user);
        if(!save){
            return Result.fail("服务器出错");
        }
        return generateTokenAndSaveUser(user);
    }

    /**
     * 登录功能
     * @param loginForm 登录参数，包含手机号、验证码；或者用户名、密码，登录类型
     */
    @Override
    public Result login(LoginFormDTO loginForm) {
        // 判断登录方式
        if (loginForm.getLoginType() == 1) {
            // 手机号+验证码登录
            return loginByPhoneAndCode(loginForm);
        } else if (loginForm.getLoginType() == 2) {
            // 用户名+密码登录
            return loginByUsernameAndPassword(loginForm);
        } else {
            return Result.fail("不支持的登录方式");
        }
    }
    /**
     * 手机号+验证码登录
     */
    public Result loginByPhoneAndCode(LoginFormDTO loginForm) {
        String phone = loginForm.getPhone();
        if(RegexUtils.isPhoneInvalid(phone)){
            return Result.fail("手机号格式错误！");
        }
        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY+phone);
        String code = loginForm.getCode();
        if(cacheCode==null||!cacheCode.equals(code)){
            return Result.fail("验证码失效或错误");
        }
        User user = query().eq("phone", phone).one();
        if(user == null) {
            user = createUserWithPhone(phone);
        }
        return generateTokenAndSaveUser(user);
    }
    /**
     * 用户名+密码登录
     */
    private Result loginByUsernameAndPassword(LoginFormDTO loginForm) {
        String username = loginForm.getName();
        String password = loginForm.getPassword();

        if (StrUtil.isBlank(username) || StrUtil.isBlank(password)) {
            return Result.fail("用户名或密码不能为空");
        }

        User user = query().eq("name", username).one();
        if (user == null) {
            return Result.fail("用户未注册,请先完成注册");
        }
        if (!BCrypt.checkpw(password, user.getPassword())){
            return Result.fail("用户名或密码错误");
        }

        return generateTokenAndSaveUser(user);
    }

    /**
     * 生成token并保存用户信息到Redis
     */
    private Result generateTokenAndSaveUser(User user) {
        String token = UUID.randomUUID().toString(true);
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map<String, Object> userMap = BeanUtil.beanToMap(
                userDTO,
                new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(false)
                        .setFieldValueEditor((fieldName, fieldValue) ->
                                fieldValue != null ? fieldValue.toString() : ""
                        )
        );
        stringRedisTemplate.opsForHash().putAll(LOGIN_USER_KEY+token,userMap);
        stringRedisTemplate.expire(LOGIN_USER_KEY+token,CACHE_USER_TTL,TimeUnit.MINUTES);
        return Result.ok(token);
    }

    /**
     * 根据手机号创建用户
     * @param phone 手机号
     */
    private User createUserWithPhone(String phone) {
        User user = new User();
        user.setPhone(phone);
        user.setName(USER_NAME_PREFIX+RandomUtil.randomString(10));
        save(user);
        return user;
    }

}